#include "fatfs_.h"
// 表示文件系统
static FATFS fatfs;
// 文件系统是否挂载成功
static bool fatfsStatus;

/**
 * @desc  : 文件系统初始化
 * @date  : 2025-05-14
 * @author: AnRui
 * @note  :
 */
void FatfsInit(void)
{
//    uint8_t workBuffer[FF_MAX_SS];
//    f_mkfs(DEV_PATH_STR, 0, workBuffer, FF_MAX_SS);
//    return;
    FRESULT res;
    // 1代表立即挂载  DEV_PATH_STR 代指驱动器
    // 检查驱动器中是否有文件系统的必要信息，如果有就挂载。挂载:将物理存储设备（卷）与文件系统关联
    res = f_mount(&fatfs, DEV_PATH_STR, 1);
    // 第一次 物理设备中是没有文件系统的信息的
    if (res == FR_NO_FILESYSTEM) {
        // 提供一个扇区大小的缓冲区 供文件系统初始化使用 FF_MAX_SS:4096
        // 要注意栈空间
        uint8_t workBuffer[FF_MAX_SS];
        res = f_mkfs(DEV_PATH_STR, 0, workBuffer, FF_MAX_SS);
        // 向物理设备中存储文件系统需要的基础信息
        // 0:代表根据 文件系统 配置的扇区个数和大小 自己选择文件系统格式
        // 提供一个工作区
        res = f_mkfs(DEV_PATH_STR, 0, workBuffer, FF_MAX_SS);
        if (res == FR_OK) {
            /* 格式化后，先取消挂载 */
            f_mount(NULL, DEV_PATH_STR, 1);
            /* 重新挂载 */
            res = f_mount(&fatfs, DEV_PATH_STR, 1);
        }
    }
    if (res != FR_OK) {
        printf("文件系统初始化失败，错误码：%d.\n", res);
        fatfsStatus = false;
        return;
    }
    printf("fatfs init successful\r\n");
    fatfsStatus = true;
}




/**
 * @desc  : 文件系统综合测试
 * @date  : 2025-05-20
 * @author: AnRui
 * @note  :
 */
void FatfsTestTask(void)
{
    if (!fatfsStatus) {
        printf("fatfs init error \n");
        return;
    }
    FRESULT res; //结果
    UINT bytes_written; //写数量
    FIL file;//文件句柄
    DIR dir;// 目录句柄
    FILINFO fno;//文件信息
    char file_path[64];// 文件路径缓冲区
    char buffer[256];//文件读取缓冲区

    // 1. 创建文件夹
    res = f_mkdir("C:/myfolder");
    if (res == FR_OK) {
        printf("foler create successful\n");
    } else if (res == FR_EXIST) {
        printf("foler existed\n");
    } else {
        printf("foler create error,code%d\n", res);
        return;
    }
    // 2. 创建并写入文件1
    char* test1 = "test data adfadfadf 1\n";
    char* test2 = "test dats d阿斯顿发的发a法撒旦法2\n";
    res = f_open(&file, "C:/myfolder/file1.txt", FA_CREATE_ALWAYS | FA_WRITE);
    if (res == FR_OK) {
        f_printf(&file, "%s\n", test1);
        f_printf(&file, "%s\n", test2);
        f_close(&file);
    } else {
        printf("file1  create error,code%d\n", res);
        return;
    }

    // 3. 创建并写入文件2（混合使用f_printf和f_write）
    test1 = "test data adfadfadf 3\n";
    test2 = "test data adfadfadf 4\n";
    // f_write f_print 写数据时 不回把\0写进去
    // f_get会把 \n 读出来
    // 写入\n 实际是写入了\r\n
    res = f_open(&file, "C:/myfolder/file2答复.txt", FA_OPEN_APPEND | FA_WRITE);
    if (res == FR_OK) {
        f_write(&file, test1, strlen(test1), &bytes_written);
        f_write(&file, test2, strlen(test2), &bytes_written);
        f_close(&file);
    } else {
        printf("file2  create error,code%d\n", res);
        return;
    }

    // 4. 读取文件夹中所有文件内容
    res = f_opendir(&dir, "C:/myfolder");
    if (res == FR_OK) {
        printf("\n=== foler context===\n");
        // 打印文件夹中所有的文件
        while (f_readdir(&dir, &fno) == FR_OK && fno.fname[0]) {
            // 目录
            if (fno.fattrib & AM_DIR) {
                printf("\nfolername: %s\n", fno.fname);
            }
            // 文件
            else {
                printf("\nfile name: %s\n", fno.fname);
                //构造文件路径
                sprintf(file_path, "myfolder/%s", fno.fname);
                res = f_open(&file, file_path, FA_READ);
                if (res == FR_OK) {
                    while (!f_eof(&file)) {
                        //把缓冲区所有的数据都替换成0
                        memset(buffer, 0, sizeof(buffer));
                        if (f_gets(buffer, sizeof(buffer), &file) != NULL) {
                            printf("%s", buffer); // 注意：f_gets已包含换行符
                        }
                    }
                    f_close(&file); // 关闭已读取的文件
                } else {
                    printf("\n  file open  error,code%d\n", res);
                }
            }
        }
        f_closedir(&dir); // 关闭目录
    } else {
        printf("\n=== foler open error ===\n");
        return;
    }
    f_closedir(&dir);
    // 5. 使用f_findfirst查找文件
    res = f_opendir(&dir, "C:/myfolder");
    if (res != FR_OK) {
        printf(" foler open error,code %d\n", res);
        return;
    }

    printf("\n=== f_findfirst find file ===\n");
    res = f_findfirst(&dir, &fno, "C:/myfolder", "*.txt");
    while (res == FR_OK && fno.fname[0]) {
        // 打印文件名
        printf("find file success: %s\n", fno.fname);
        // 判断是否为目录
        if (fno.fattrib & AM_DIR) {
            printf("foler\n");
        } else {
            printf("file size %u\n", fno.fsize);
        }
        // 查找下一个文件
        res = f_findnext(&dir, &fno);
    }
    // 关闭目录
    f_closedir(&dir);

    // 6. 删除文件和文件夹
    res = f_unlink("C:/myfolder/file1.txt");
    if (res == FR_OK) printf("\nfile1 del success\n");

    res = f_unlink("C:/myfolder/file2.txt");
    if (res == FR_OK) printf("\nfile2 del success\n");

    res = f_rmdir("C:/myfolder");
    if (res == FR_OK) printf("\n folder del success\n");
}


/**
 * @desc  : 打印文件信息
 * @date  : 2025-05-20
 * @author: AnRui
 * @param : filePath - {鍙傛暟璇存槑}:
 * @note  :
 */
void PrintFileInfo(const char* filePath)
{
    FILINFO fileInfo;
    FRESULT res;
    res = f_stat(filePath, &fileInfo);
    if (res != FR_OK) {
        return;
    }

    printf("%s文件信息:\n", fileInfo.fname);
    printf(">>文件大小: %d(字节)\n", fileInfo.fsize);
    printf(">>时间戳: %u-%02u-%02u, %02u:%02u:%02u\n",
           (fileInfo.fdate >> 9) + 1980, fileInfo.fdate >> 5 & 15, fileInfo.fdate & 31,
           fileInfo.ftime >> 11, fileInfo.ftime >> 5 & 63, (fileInfo.ftime & 31) * 2);
    printf(">>属性: %c%c%c%c%c\n\n",
           (fileInfo.fattrib & AM_DIR) ? 'D' : '-',      // 是一个目录
           (fileInfo.fattrib & AM_RDO) ? 'R' : '-',      // 只读文件
           (fileInfo.fattrib & AM_HID) ? 'H' : '-',      // 隐藏文件
           (fileInfo.fattrib & AM_SYS) ? 'S' : '-',      // 系统文件
           (fileInfo.fattrib & AM_ARC) ? 'A' : '-');     // 档案文件
}
